home *** CD-ROM | disk | FTP | other *** search
/ Risc World 3 / Risc World 3.iso / SOFTWARE / ISSUE6 / PD / PDF / pdf / c++ / DrawOutputFont < prev    next >
Text File  |  2003-02-17  |  13KB  |  444 lines

  1. //--------------------------------------------------------------------------
  2. //
  3. //   Copyright (c) 2002, Colin Granville
  4. //
  5. //   All rights reserved.
  6. //
  7. //   Redistribution and use in source and binary forms, with or
  8. //   without modification, are permitted provided that the following 
  9. //   conditions are met:
  10. //
  11. //      * Redistributions of source code must retain the above copyright 
  12. //        notice, this list of conditions and the following disclaimer.
  13. //
  14. //      * Redistributions in binary form must reproduce the above 
  15. //        copyright notice, this list of conditions and the following 
  16. //        disclaimer in the documentation and/or other materials 
  17. //        provided with the distribution.
  18. //
  19. //      * The name Colin Granville may not be used to endorse or promote 
  20. //        products derived from this software without specific prior 
  21. //        written permission.
  22. //
  23. //   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  24. //   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
  25. //   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
  26. //   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
  27. //   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
  28. //   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
  29. //   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  30. //   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  31. //   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  32. //   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  33. //   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
  34. //   OF THE POSSIBILITY OF SUCH DAMAGE.
  35. //
  36. //--------------------------------------------------------------------------
  37.  
  38. #include "DrawOutputFont.h"
  39. #include "GfxFont.h"
  40. #include "GfxState.h"
  41. #include <math.h>
  42. #include <stdlib.h>
  43. #include <ctype.h>
  44. #include "ucompare.h"
  45. #include <iostream.h>
  46. #include "PdfDocEncoding.h"
  47. #include "GlobalParams.h"
  48. #include "iostream.h"
  49. #include "FontEncodingTables.h"
  50.  
  51. #define DEFAULT_FONT_LIST_SIZE 14
  52.  
  53. double charWidths[DEFAULT_FONT_LIST_SIZE][256];
  54.  
  55. struct FontFace
  56. {
  57.   const char*        pdfName;
  58.   const char*        riscOsName;
  59.   UnicodeToAcornMap* map;
  60.   double*            charWidth;
  61. } defaultFonts[DEFAULT_FONT_LIST_SIZE] = {
  62.   {"Courier",                   "Corpus.Medium",            0,    charWidths[0]},
  63.   {"Courier-Bold",              "Corpus.Bold",              0,    charWidths[1]},
  64.   {"Courier-Oblique",           "Corpus.Medium.Oblique",    0,    charWidths[2]},
  65.   {"Courier-BoldOblique",       "Corpus.Bold.Oblique",      0,    charWidths[3]},
  66.   {"Helvetica",                 "Homerton.Medium",          0,    charWidths[4]},
  67.   {"Helvetica-Bold",            "Homerton.Bold",            0,    charWidths[5]},
  68.   {"Helvetica-Oblique",         "Homerton.Medium.Oblique",  0,    charWidths[6]},
  69.   {"Helvetica-BoldOblique",     "Homerton.Bold.Oblique",    0,    charWidths[7]},
  70.   {"Times-Roman",               "Trinity.Medium",           0,    charWidths[8]},
  71.   {"Times-Bold",                "Trinity.Bold",             0,    charWidths[9]},
  72.   {"Times-Italic",              "Trinity.Medium.Italic",    0,    charWidths[10]},
  73.   {"Times-BoldItalic",          "Trinity.Bold.Italic",      0,    charWidths[11]},
  74.   {"Symbol",                    "Sidney",                   0,    charWidths[12]},
  75.   {"ZapfDingbats",              "Selwyn",                   0,    charWidths[13]}
  76. };
  77.  
  78. class InitDefaultFonts
  79. {
  80.   public:
  81.     UnicodeToAcornMap latin1;
  82.     UnicodeToAcornMap symbol;
  83.     UnicodeToAcornMap dingbats;
  84.     InitDefaultFonts();
  85. } initDefaultFonts;
  86.  
  87. InitDefaultFonts::InitDefaultFonts()
  88.   : latin1(unicodeToAcornLatin1),
  89.     symbol(unicodeToAcornSymbol),
  90.     dingbats(unicodeToAcornDingbats)
  91. {
  92.   int f;
  93.   for (f=0;f<DEFAULT_FONT_LIST_SIZE;f++)
  94.   {
  95.     if (f==DEFAULT_FONT_LIST_SIZE-1) defaultFonts[f].map=&dingbats;
  96.     else if (f==DEFAULT_FONT_LIST_SIZE-2) defaultFonts[f].map=&symbol;
  97.     else defaultFonts[f].map=&latin1;
  98.   }
  99.  
  100.   for (f=0;f<DEFAULT_FONT_LIST_SIZE;f++)
  101.   {
  102.     int handle=0;
  103.     _swix(Font_FindFont,_INR(1,5) | _OUT(0), defaultFonts[f].riscOsName,16,16,0,0,&handle);
  104.     if (handle) 
  105.     {
  106.       int spacewidth=0;
  107.       _swix(Font_ScanString,_INR(0,5) | _OUT(3), 0,"  ",0,-1,-1,0,&spacewidth);
  108.       int i;
  109.       for (i=0;i<32;i++) charWidths[f][i]=0;
  110.       char s[4];
  111.       s[0]=' ';s[2]=' ';s[3]=0;
  112.       for (i=32;i<256;i++)
  113.       {
  114.         int size=spacewidth;
  115.         s[1]=i;
  116.         _swix(Font_ScanString,_INR(0,5) | _OUT(3), 0,s,0,-1,-1,0,&size);
  117.         charWidths[f][i]=double(size-spacewidth)/1000.0;
  118.       }
  119.       if (f<DEFAULT_FONT_LIST_SIZE-2) charWidths[f][0x8f]=0;//dont alter shape of bullet
  120.       _swix(Font_LoseFont,_IN(0),handle);
  121.     }
  122.   }
  123. }
  124.  
  125. //*****************************************************************
  126. //*****************************************************************
  127. //*****************************************************************
  128.  
  129. DrawOutputFontList::DrawOutputFontList()
  130.  : fontList(0),
  131.    handle(0)
  132. {
  133.   flags=0;
  134. }
  135.  
  136. //*****************************************************************
  137.  
  138. DrawOutputFontList::~DrawOutputFontList() {clear();}
  139.  
  140. //*****************************************************************
  141.  
  142. void DrawOutputFontList::declareFonts()
  143. {
  144.   int i;
  145.   for (i=0;i<DEFAULT_FONT_LIST_SIZE;i++)
  146.   {
  147.     _swix(PDriver_DeclareFont,_INR(0,2),0,defaultFonts[i].riscOsName,0);
  148.   }
  149. }
  150.  
  151. //*****************************************************************
  152.  
  153. const char* DrawOutputFontList::getUsedFont(int fontIndex)
  154. {
  155.   fontIndex--;
  156.   if (fontIndex<0 || fontIndex>=DEFAULT_FONT_LIST_SIZE) return 0;
  157.   return defaultFonts[fontIndex].riscOsName;
  158. }
  159.  
  160. //*****************************************************************
  161.  
  162. void DrawOutputFontList::clear()
  163. {
  164.   lose();
  165.  
  166.   DrawOutputFont* f=fontList;
  167.   DrawOutputFont* next=0;
  168.   for (;f;f=next) {next=f->next;delete f;}
  169.  
  170.   fontList=0;
  171. }
  172.  
  173. //*****************************************************************
  174.  
  175. void DrawOutputFontList::atExit()
  176. {
  177.   lose();
  178. }
  179.  
  180. //*****************************************************************
  181.  
  182. void DrawOutputFontList::find(GfxState& state)
  183. {
  184.   if (fontList==0) return;
  185.   double fontsize=(state.getFont() ? state.getFontSize() : 10.0);
  186.   int newFontXSize= int(fontsize*matXScale*state.getHorizScaling()) ;
  187.   if (newFontXSize<40) newFontXSize=40; //causes redraw problems if size < 1/16 pt
  188.  
  189.   int newFontYSize= (int)(fontsize*matYScale);
  190.   if (newFontYSize<40) newFontYSize=40; //causes redraw problems if size < 1/16 pt
  191.   
  192.   if (font==fontList->getFontIndex() && newFontYSize==fontYSize && newFontXSize==fontXSize) return;
  193.   fontXSize=newFontXSize;
  194.   fontYSize=newFontYSize;
  195.   font=fontList->getFontIndex();
  196.   int oldhandle=handle;
  197.   _swix(Font_FindFont,_INR(1,5) | _OUT(0), fontList->getRiscOsFontName(),
  198.                                            fontXSize/40,
  199.                                            fontYSize/40,
  200.                                            0,
  201.                                            0,
  202.                                            &handle);
  203.   if (oldhandle) _swix(Font_LoseFont,_IN(0),oldhandle);
  204. }
  205.  
  206. //*****************************************************************
  207.  
  208. void DrawOutputFontList::lose()
  209. {
  210.   if (handle) 
  211.   { 
  212.     _swix(Font_LoseFont,_IN(0),handle);
  213.     handle=0;
  214.   }
  215. }
  216.  
  217. //*****************************************************************
  218.  
  219. void DrawOutputFontList::setMatrix(GfxState& state)
  220. {
  221.   double* ctm=state.getCTM();
  222.   double* tm=state.getTextMat();
  223.  
  224.   //calculate x scale
  225.   double a = tm[0]*ctm[0] + tm[1]*ctm[2];
  226.   double b = tm[0]*ctm[1] + tm[1]*ctm[3];
  227.   double scale = sqrt(a*a+b*b);
  228.   charMatrix[0]=(a*65536.0/scale);
  229.   transform.m0 = (int)charMatrix[0];
  230.   charMatrix[1]=(b*65536.0/scale);
  231.   transform.m1 = (int)charMatrix[1];
  232.   matXScale=scale;
  233.  
  234.   //calculate y scale
  235.   a=tm[2]*ctm[0] + tm[3]*ctm[2];
  236.   b=tm[2]*ctm[1] + tm[3]*ctm[3];
  237.   scale=sqrt(a*a+b*b);
  238.   transform.m2 = (int)(a*65536.0/scale);
  239.   transform.m3 = (int)(b*65536.0/scale);
  240.   matYScale=scale;
  241. }
  242.  
  243. //*****************************************************************
  244.  
  245. void DrawOutputFontList::setCharMatrix(double fromWid, double toWid)
  246. {
  247.   double scale= (fromWid!=0 && toWid !=0 ? fromWid/toWid :1.0);
  248.   transform.m0=(int)(charMatrix[0]*scale);
  249.   transform.m1=(int)(charMatrix[1]*scale);
  250. }
  251.  
  252. //*****************************************************************
  253.  
  254. void DrawOutputFontList::set(GfxState& state)
  255. {
  256.   setMatrix(state);
  257.   GfxFont* gfxFont=state.getFont();
  258.   DrawOutputFont* f=fontList;
  259.   DrawOutputFont* last=0;
  260.   for (;f;last=f,f=f->next)
  261.   {
  262.     if (gfxFont==f->getFont())
  263.     {
  264.       if (last)
  265.       {
  266.         last->next=f->next;
  267.         f->next=fontList;
  268.         fontList=f;
  269.       }
  270.       find(state);
  271.       return;
  272.     }
  273.   }
  274.  
  275.   f=new DrawOutputFont(gfxFont);
  276.   if (f)
  277.   {
  278.     f->next=fontList;
  279.     fontList=f;
  280.     find(state);
  281.   }
  282. }
  283.  
  284. //*****************************************************************
  285. //*****************************************************************
  286. //*****************************************************************
  287.  
  288. DrawOutputFont::DrawOutputFont(GfxFont* gfxFont)
  289.   : font(gfxFont),
  290.     mapStore(0)
  291. {
  292.  
  293.   if (!gfxFont)
  294.   {
  295.     getSubstituteFont(0);
  296.     return;
  297.   }
  298.  
  299.   GString*font_name=gfxFont->getName();
  300.   if (!font_name) font_name = gfxFont->getEmbeddedFontName();
  301.   if (!font_name || !findFont(font_name->getCString())) 
  302.   {  
  303.     getSubstituteFont(font_name?font_name->getCString():0);
  304.   }
  305.  return;
  306. }
  307.  
  308. //*****************************************************************
  309.  
  310. DrawOutputFont::~DrawOutputFont()
  311. {
  312.   delete mapStore;
  313. }
  314.  
  315. //*****************************************************************
  316.  
  317. void DrawOutputFont::getSubstituteFont(const char* name)
  318. {
  319.   if (font==0)
  320.   {
  321.     riscOsFontName=defaultFonts[0].riscOsName;
  322.     map=defaultFonts[0].map;
  323.     charWidth=defaultFonts[0].charWidth;
  324.     fontIndex=1;
  325.     return;
  326.   }
  327.  
  328.   int i=4;
  329.   if (name)
  330.   {
  331.     if (font->isSerif() || 
  332.         uFind(name,"times") ||
  333.        (!uFind(name,"sans") && uFind(name,"serif")) ||
  334.         uFind(name,"Garamond")) i=8;
  335.     if (font->isFixedWidth() || uFind(name,"courier")) i=0;   
  336.     
  337.     if (font->isItalic() || uFind(name,"obli") || uFind(name,"ital") ) i|=2;
  338.     if (font->isBold() || uFind(name,"bold")|| uFind(name,"black"))   i|=1;
  339.   }
  340.   else i=8;//serif font
  341.  
  342.  
  343.   map=defaultFonts[i].map;
  344.   riscOsFontName=defaultFonts[i].riscOsName;
  345.   charWidth=defaultFonts[i].charWidth;
  346.   fontIndex=i+1;
  347. }
  348.  
  349. //*****************************************************************
  350.  
  351. bool DrawOutputFont::findFont(const char* name)
  352. {
  353.   if (name==0) return 0;
  354.   const char* n=name;
  355.   while (!(*n==0 || *n=='+' || *n=='-')) n++;
  356.   if (*n=='+') name=n+1;
  357.   int i;
  358.   for (i=0;i<DEFAULT_FONT_LIST_SIZE;i++)
  359.   {
  360.     if (uCompare(name,defaultFonts[i].pdfName)==0)
  361.     {
  362.       riscOsFontName=defaultFonts[i].riscOsName;
  363.       map=defaultFonts[i].map;
  364.       charWidth=defaultFonts[i].charWidth;
  365.       fontIndex=i+1;
  366.       return 1;
  367.     }
  368.   }
  369.   return 0;
  370. }
  371.  
  372. //*****************************************************************
  373. //*****************************************************************
  374. //*****************************************************************
  375.  
  376. class StandardFontToAcornLatin1
  377. {
  378.    public:
  379.      StandardFontToAcornLatin1();
  380.      unsigned char getChar(const unsigned char c) {return map[c];}
  381.    private:
  382.      unsigned char map[256];
  383.  
  384. };
  385.  
  386. StandardFontToAcornLatin1& standardFontToAcornLatin1()
  387. {
  388.   static StandardFontToAcornLatin1 p;
  389.   return p;
  390. }
  391.  
  392. //*****************************************************************
  393.  
  394. StandardFontToAcornLatin1::StandardFontToAcornLatin1()
  395. {
  396.    for (int i=0;i<256;i++)
  397.    {
  398.      map[i]=0;
  399.      char* name=pdfDocEncoding[i];
  400.      if (name)
  401.      {
  402.        Unicode u=globalParams->mapNameToUnicode(name);
  403.        if (u) map[i]=initDefaultFonts.latin1.getChar(u);
  404.      }
  405.    }
  406. }
  407. //*****************************************************************
  408.  
  409. string toAcornLatin1(const char* str, int len)
  410. {
  411.   string res;
  412.   unsigned char* p=(unsigned char*)str;
  413.  
  414.   if (p[0]==0xfe && p[1]==0xff)
  415.   {
  416.     res.reserve(len/2);
  417.     for (int i=2;i<len;i+=2)
  418.     {
  419.       unsigned char c=initDefaultFonts.latin1.getChar(p[i]+p[i+1]*256);
  420.       if (c!=UnicodeToAcornMap::NO_CONVERSION_CHAR) res+=c;
  421.     }
  422.   }
  423.   else if (p[0]==0xff && p[1]==0xfe)
  424.   {
  425.     res.reserve(len/2);
  426.     for (int i=2;i<len;i+=2)
  427.     {
  428.       unsigned char c=initDefaultFonts.latin1.getChar(p[i+1]+p[i]*256);
  429.       if (c!=UnicodeToAcornMap::NO_CONVERSION_CHAR) res+=c;
  430.     }
  431.   }
  432.   else
  433.   {
  434.     StandardFontToAcornLatin1& s = standardFontToAcornLatin1();
  435.     res.reserve(len);
  436.     for (int i=0;i<len;i++)
  437.     {
  438.        unsigned char c = s.getChar(p[i]);
  439.        if (c) res+=(char)c;
  440.     }
  441.   }
  442.   return res;
  443. }
  444.